/*
 * SynchronizedQueue.java	2008/07/28
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
import java.util.Collections;
import java.util.Properties;

/**
 * Use this class if you are in a multithread environment. 
 * @author Leonardo Celati
 * @param <T> Anything extends Entry
 */
@SuppressWarnings("unchecked")
final class SynchronizedQueue<T extends Entry> extends Queue<T> implements Cumulable {

	/**
	 *  The Entry container for this Queue
	 */
	private List<T> l;
	/**
	 * Interval before wakeup the QueueDumper
	 */
	private long wakeup;
	/**
    * Marker for wakeup QueueDumper 
     */
	private long mark;
	
	/**
	 * Default constructor 
	 */
	public SynchronizedQueue(Properties p) {
		super(p);
		l = new ArrayList<T>();
		this.wakeup = Constant.DEFAULT_SYNCHRONIZED_QUEUE_WAKEUP;
		this.mark = System.currentTimeMillis();
	}

	/**
	 * See if this cell is empty
	 * @return true if it's empty, false if not
	 */
	public synchronized boolean isEmpty() {
		return l.isEmpty();
	}

	/**
	 * Store the element into the Queue
	 * @param T
	 * @return true if the element is correctly added to queue
	 */
	public synchronized boolean push(T t) {
		// adding to Queue
		boolean added = l.add(t);
		// when the Queue is not empty and the current time is greater
		// than the latest mark, then we can wake up the QueueDumper
		if (!this.isEmpty() && System.currentTimeMillis() - mark > wakeup) {
			notifyAll();
			// after notifing the QueueDumper
			// then we set a new marker...
			mark = System.currentTimeMillis();
		}
		// returning...
		return added;
	}

	/**
	 * 
	 * @return a sorted list containing all entry
	 */
	public synchronized LinkedList<T> retainAll() {
		
		// let's tell the QueueDumper to wait...
		try {
			wait();				
		} catch (InterruptedException e) {
			Log.serviceLog(e);
		}
		
		// our entry will goes in there
		LinkedList<T> ll = new LinkedList<T>();
		// sort T
		Collections.sort(this.l);
		// time to iterate trough the container
		Iterator<T> i = this.l.iterator();
		// each element in container is added to the list
		while (i.hasNext()) {
			ll.add(i.next());
		}
		// cleaning the old queue
		this.l.clear();
		// returning the new one
		return ll;
	}

	/**
	 * Retrieve the actual size of this queue
	 * @return the size of this cell
	 */
	public synchronized int size() {
		return l.size();
	}

}
